package org.acooke.uykfd.db

import java.sql.Connection

import org.jgrapht.graph.DefaultWeightedEdge
import org.jgrapht.graph.SimpleDirectedGraph

import scala.collection.JavaConversions._
import scala.util.Random


trait LfmArtistBacklinkRow
  extends EdgeRow[ArtistRow] {

  def other(node: ArtistRow, cnxn: Connection): ArtistRow
//  def otherDegree(node: ArtistRow, cnxn: Connection): Int
}

trait LfmArtistBacklinkTable
  extends EdgeTable[
    LfmArtistBacklinkRow, ArtistRow, Schema.Artists, LfmArtistBacklinkTable, 
    Schema.LfmArtistBacklinks
  ] {

  def build(maxDegreeBack: Int, maxDegreeFwd: Int, cnxn: Connection)
  def allEdges(artist: ArtistRow, cnxn: Connection): List[LfmArtistBacklinkRow]
  def outDegree(artist: ArtistRow, cnxn: Connection): Int
  def inDegree(artist: ArtistRow, cnxn: Connection): Int
  def toDirectedGraph(cnxn: Connection): SimpleDirectedGraph[Int, DefaultWeightedEdge]
  def show(name: String, maxDegreeBack: Int, maxDegreeFwd: Int, cnxn: Connection): Unit
  def show(cnxn: Connection): Unit
}

private class LfmArtistBacklinkFactory
  extends EdgeFactory[
    ArtistRow, Schema.Artists, LfmArtistBacklinkRecord, LfmArtistBacklinkTable, 
    Schema.LfmArtistBacklinks
  ](Schema.LFM_ARTIST_BACKLINKS, Schema.ARTISTS, Schema.ARTISTS.orm.fromId)
  with LfmArtistBacklinkTable {

  def rowFactory = new LfmArtistBacklinkRecord(nodeFactory)

  def build(maxDegreeBack: Int, maxDegreeFwd: Int, cnxn: Connection) = {
    erase(cnxn)
    fromGraph(Schema.LFM_ARTIST_CONNECTIONS.orm.toDirectedBacklinkGraph(
      maxDegreeBack, maxDegreeFwd, cnxn), cnxn)
  
  }

  def allEdges(artist: ArtistRow, cnxn: Connection) = fromSource(artist, cnxn)

  def show(name: String, maxDegreeBack: Int, maxDegreeFwd: Int, cnxn: Connection) = {
    Schema.ARTISTS.orm.lookupValue(name, cnxn) match {
      case Some(artist) =>
        println("\nactual:")
        for (edge <- allEdges(artist, cnxn)) println("  " + edge.other(artist, cnxn))
        println("\nforwards:")
        show_original(artist, maxDegreeFwd, cnxn)
        println("\nbacklinks:")
        for (edge <- allEdges(artist, cnxn)) {
          val target = edge.sink(cnxn)
          println(target.value)
          show_original(target, maxDegreeBack, cnxn)
        }
      case None => println(name + " not found")
    }
  }

  def show_original(artist: ArtistRow, maxDegree: Int, cnxn: Connection) = {
    val links = Schema.LFM_ARTIST_CONNECTIONS.orm.sortedEdges(artist, cnxn)
    val next = links.iterator
    for (_ <- 1.to(Math.min(maxDegree, links.size))) {
      val backlink = next.next
      println("  " + backlink.other(artist, cnxn) + " " + backlink.weight)
    }
  }

  def show(cnxn: Connection) =
    showConnected(toDirectedGraph(cnxn), Schema.ARTISTS.orm.fromId(_, cnxn).value)

}

private class LfmArtistBacklinkRecord(nf: (Int, Connection) => ArtistRow)
  extends EdgeRecord[
    ArtistRow, Schema.Artists, LfmArtistBacklinkRecord, LfmArtistBacklinkTable, 
    Schema.LfmArtistBacklinks
  ](Schema.LFM_ARTIST_BACKLINKS, nf)
  with LfmArtistBacklinkRow {

//  def otherDegree(artist: ArtistRow, cnxn: Connection) = 
//    if (sourceId == artist.id) Schema.LFM_ARTIST_BACKLINKS.orm.inDegree(sink(cnxn), cnxn)
//    else if (sinkId == artist.id) Schema.LFM_ARTIST_BACKLINKS.orm.outDegree(source(cnxn), cnxn)
//    else 0

}
